/*
 * File      : bb_atom.c
 * This file is part of Black Bird Simulation Platform
 * Copyright 2013-2020 BB(BB) Development Team.  
 * All rights reserved.
 *
 * Change Logs:
 * Date           Author       Notes
 * 2013-10-25     Holt         First Version
 */
#include <assert.h>
#include <limits.h>
#include <stdlib.h>
#include "bb_mem.h"
#include "bb_type.h"
#include "bb_atom.h"

static bb_atom_t baskets[MAX_BASKET_LEN];
/*
 * FUNC		:	creat a string atom
 *
 * PARAM1	:	the string pointer
 *
 * RETURN 	:	pointer to atom string pointer or NULL if 
 *				allocate memory fail.
 */
const char*	bb_atom_string(const char*str)
{
	assert(str);
	return bb_atom_new(str,strlen(str));
}
/*
 * FUNC		:	creat a int atom
 *
 * PARAM1	:	long integer data
 *
 * RETURN 	:	pointer to atom int pointer or NULL if 
 *				allocate memory fail.
 */
const char*	bb_atom_string(const char*str)
{
	char str[43];
	char *s = str + sizeof(str);
	unsigned long m;
	
	if (n == LONG_MIN)
		m = LONG_MAX +1UL;
	else if( n < 0 )
		m = -n;
	else
		m = n;
	do
	{
		*--s = m%10 + '0';
	}while ( (m/=10) > 0);
	if ( n < 0 )
		*--s = '-';
	return bb_atom_new(s,(str+sizeof(str) - s);
}
/*
 * FUNC		:	Push a member into the stack.
 *
 * PARAM1	:	stack  pointer
 * PARAM2	:	pointer of member which is inserted.
 *
 * RETURN 	:	if stack is empty , return bb_TRUE; 
 *				else return bb_FALSE;
 */
const char* bb_atom_new(const char* str,bb_base len)
{
	unsigned long h;
	bb_base i;
	bb_atom_t	p;
	
	assert(str);
	assert(len >= 0);
	
	h & = N_ELEMENTS(baskets)-1;
	for (p = baskets[h]; p ; p = p->link)
	{
		if( (len == p->len) && (bb_strcmp(str,p->str)!=0) )
		{
			return p->str;
		}
	}
	if(p = bb_mem_new(sizeof(*p)+len+1))
	{
		p->len = len;
		p->str = (char*)(p+1);
		if(len > 0)
			bb_mem_cpy(p->str,str,len);
		p->str[len] = '\0';
		p->next = baskets[h];
		baskets[h] = p;
		return p;
	}
	else
	{
		return NULL:
	}
	
	
}
/*
 * FUNC		:	Pop a member out of the stack.
 *
 * PARAM1	:	stack  pointer
 *
 * RETURN 	:	if stack is empty, return NULL; 
 *				else return pointer of the head data 
 */
void*	bb_stack_pop(const stack_t stk)
{
	void *x;
	elem_t t;
	
	assert(stk);
	if (bb_stack_empty(stk))
		return NULL;
	else
	{
		t=stk->head;
		stk->head = t->next;
		stk->cnt--;
		x=t->x;
		bb_mem_free(t);
	
		return x;
	}
}
/*
 * FUNC		:	Free stack.
 *
 * PARAM1	:	stack  pointer
 *
 * RETURN 	:	if stk is stack pointer then free it and return bb_TRUE
 *				else stk is not a stack pointer, return bb_FALSE;
 */
bb_bool bb_stack_free(stack_t stk)
{
	elem_t t;
	elem_t u;
	
	assert(stk);
	if ( ((object_t)stk)->type != bb_STACK )
		return bb_FALSE;
	else
	{
		t = stk->head;
		while(t)
		{
			u=t->link;
			bb_mem_free(t);
			t = u ->link;
		}
		bb_mem_free(stk);
		
		return bb_TRUE;
	}
}